Node测试基础

万法皆学问。
那就简单处理。

2021.7.5 星期一 00:08

“测试驱动开发”(TDD:Test-Driven Development)

测试大分类
业务功能:正常场景,异常场景
边界分析:
性能测试:响应时间,吞吐量,并发,资源使用率(cpu,内存,网络传输,io)
安全测试:信息加密,sql 注入

接口测试

1.什么是接口?
2.接口都有哪些类型?
3.接口的本质是什么?
4.什么是接口测试?
5.问什么要做接口测试?
6.怎样做接口测试?
7.接口测测试点是什么?
8.接口测试都要掌握哪些知识?
9.其他相关知识?

接口分类

主要包含三种测试:
Web接口测试,
应用程序接口测试,
数据库测试。

外部接口,内部接口:上层服务于下层服务,同级服务。常见的接口分类http:get,post,delete,put

系统对外的接口:比如你要从别的网站或服务器上获取资源或信息,别人肯定不会把数据库共享给你,他只能给你提供一个他们写好的方法来获取数据,你引用他提供的接口就能使用他写好的方法,从而达到数据共享的目的。

程序内部的接口:方法与方法之间,模块与模块之间的交互,程序内部抛出的接口,

实际上意义就是UI界面到数据库之间,数据流经过的所有过程。

开始测试

流程

  1. 分析接口文档和需求文档
  2. 编写接口测试计划
  3. 编写接口测试用例
  4. 接口测试执行
  5. 输出接口测试报告。

接口用例设计原则

接口测试采用的方法其实与黑盒测试一致的,甚至可以把接口测试理解为没有界面的功能测试。

确定用例的覆盖率

工具

接口测试工具还有个最近挺火的apipost,

接口测试的工具很多,比如 postman、RESTClient、jmeter、loadrunner、SoapUI等,本人首推的测试工具是postman和jmeter,接下来就简单介绍下如何使用这两款工具进行接口测试,其他工具本次暂不介绍。

1)、Postman是谷歌的一款接口测试插件,它使用简单,支持用例管理,支持get、post、文件上传、响应验证、变量管理、环境参数管理等功能,可以批量运行,并支持用例导出、导入。

jmeter是一款100%纯Java编写的免费开源的工具,它主要用来做性能测试,相比loadrunner来说,它内存占用小,免费开源,轻巧方便、无需安装,越来越被大众所喜爱。

koa 单元测试

所谓单元测试,就是通过测试单个代码单元以测试代码的单一功能,单元测试可以让开发人发现很多潜在的问题。
JS中测试框架一般使用:mocha 、chai ,如果你还需要测试接口的话,可能还需要 supertest 测试框架。

开始测试

使用 jest+supertest 进行单元测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 3.1数据模型测试 test/model.test.js
/**
* 用户数据模型test
*/
const User = require('../src/db/model/User')

test('test user model attribute', () => {
//build会在内存模型中构建一个User对象,但不会提交到数据库中
const user = User.build({
userName: 'zhangsan',
password: '123456',
})
// 验证各个属性
expect(user.userName).toBe('zhangsan')
expect(user.password).toBe('123456')
})

// 3.2 http请求测试
//登录 test/user.test.js
test('login接口test', async () => {
const res = await server.post('/api/user/login').send({
userName,
password
})
expect(res.body.errCode).toBe(0)
//获取COOKIE,调用logout API
COOKIE = res.headers['set-cookie'].join(';')
})

使用mocha + chai测试单元

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var add = require('./add.js'); 
var expect = require('chai').expect;
describe('加法函数的测试', function() {
it('1 加 1 应该等于 2', function() {
expect(add(1, 1)).to.be.equal(2);
});
});

// 生命周期
describe('test hook', function(){
before(function() {
// 在本组测试用例开始前会执行
})
after(function() {
// 在本组测试用例结束后会执行
})
beforeEach(function() {
// 在本组每个测试用例开始前会执行
})
afterEach(function() {
// 在本组每个测试用例结束后会执行
})
})

其中 describe 称为测试套件,表示一组相关的测试。 it 称为为测试用例,表示一个单独的测试。 describe 和 it 都是 mocha 自带的全局方法。
chai是一个断言库,用于判断源码的执行结果是否与预期结果一致,如果不一致就会抛出一个错误。 expect 是 chai 其中一个断言方法。

单元测试的mock(模拟)

mocha 中的 –require 参数用于置在运行每个测试脚本运行前引入一些前置模块。我们可以利用前置脚本 mock 全局变量,保证每个测试脚本都能使用mock后的全局变量。 上面的 setup.js 脚本模拟了 global.logger.info 方法,该方法什么都不做,只是为了程序不会报 undefined 错误。

对于数据库方法 getListFromDB ,可以使用 sinon 来实现mock。 sinon 的作用是替换代码中复杂的部分以简化代码,具体使用方式请参考sinon的官网。先来看看控制器的测试脚本:

总结

1.当被测试的单元模块太大时,将模块拆分成功能单一、依赖更小的模块。
2.测试用例不是越多越好,而是越有效越好。
3.借助白盒测试的覆盖方法能体能测试代码的覆盖率。
4.当遇到一些无需测试或者难以测试的模块时,通过mock(模拟)替换这些模块。

工具

因为Koajs对ES6 generator的支持。所以在选择模块的时候需要选择相应的co封装模块。
mocha 和 co-mocha
chai
supertest 和 co-supertest

jasmine
jasmine是一个款测试工具,类似于mocha,通过它可以定义一些BDD/TDD的单元测试用例。

supertest
supertest是一款http的测试工具,可以用它来模拟http请求,并验证http请求的返回值。它最大的亮点是可以跟koa、express等框架无缝衔接。

编写单元测试代码的流程基本就是 梳理代码流程 -> 针对每一个分支编写单元测试 -> 运行单测代码 -> 查看测试覆盖率报告。

mocha介绍

mocha作为最流行的JavaScript测试框架之一,可以用于测试node.js服务和运行在浏览器环境下的js代码。

Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun.
官方给它自己定义的三个特点是simple、flexible、fun。

flexible是因为mocha本身不包含断言库、mock等功能,用户可以根据自己的需要灵活地选择所需要的额外功能。

chai断言库

mocha可以搭配你喜欢的任何断言库,经常使用到的有chai断言库。

chai提供了多种风格语法去帮助我们判断函数的执行结果。上述例子中用的是assert语法,它是基于node的assert模块进行扩展。

简单来说,断言库就是帮助我们去判断某些变量是否符合我们的要求,并且在不符合时做出错误提示。

nyc

nyc用于统计我们的单测代码测试覆盖率,使用起来也很简单:在测试脚本前加上nyc即可。

1
2
3
4
5
6
{
"scripts": {
"test": "mocha",
"coverage": "nyc npm run test"
}
}

superTest

sinon

在测试服务接口时,总会遇到一些难以模拟或者说不能随便执行的逻辑。
例如当我们需要对一个删除数据的接口进行测试时,我们不能真的去执行数据库删除操作来判断函数是否正常执行。这时候就需要引入sinon来帮助我们替换掉这些难以模拟的逻辑。

sinon库提供了三种功能:spies、stub和mock。

spies
spies功能顾名思义就是间谍函数,它能帮助我们去收集被监听函数的有关调用信息。spies作为sinon最简单的功能,它不会对被监听函数的执行过程造成任何影响,stub和mock功能都是基于spies实现的。

单元测试

如果你听说过“测试驱动开发”(TDD:Test-Driven Development),单元测试就不陌生。

定义:单元测试(unit testing)是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作

单元测试从长期来看,可以提高代码质量,减少维护成本,降低重构难度。
但是从短期来看,加大了工作量,对于进度紧张的项目中的开发人员来说,可能会成为不少的负担。

什么是单元测试

我曾经认为,单元测试面向的是一个函数。任何走出一个函数的测试,都不是单元测试。 其实,对“单元”的定义取决于自己。

谷歌看到这种“百家争鸣”的现象,创立了自己的命名方式,只分为小型测试、中型测试和大型测试。
小型测试,针对单个函数的测试,关注其内部逻辑,mock所有需要的服务。小型测试带来优秀的代码质量、良好的异常处理、优雅的错误报告.
中型测试,验证两个或多个制定的模块应用之间的交互大型测试,也被称为“系统测试”或“端到端测试”。
大型测试在一个较高层次上运行,验证系统作为一个整体是如何工作的。

结论:我们的单元测试,既可以针对一个函数写case,也可以按照函数的调用关系串起来写case。 金字塔模型

Mike Cohn 在他的着作《Succeeding with Agile》一书中提出了“测试金字塔”这个概念。
在《单元测试的艺术》这本书提到一个案例:

写好好单元测试

  1. 测试数据外部化
    测试数据大致分为两种:变化的和不变化的,对于不变的测试数据,我们完全可以写在单元测试用例代码中,也可以将数据外部化。
  2. 构建具有特定结果的测试
  3. 测试方面全面,设计的每一方面必须有一个测试用例:
  4. 测试用例请尽量简洁、简短
  5. 测试用例尽量快
  6. 每次运行单元测试时,请确保100%运行成功!
  7. 设计好你的测试
  8. 注意测试代码覆盖率
  9. 还有就是一些其他的注意点了,比如

测试策略

执行单元测试的目的:发现模块内部逻辑、语法、算法和功能错误。

单元测试主要是基于白盒测试:
验证代码与设计相符度。
发现设计和需求中存在错误。
发现在编码过程中引入的错误。

单元测试环境

单元本身不是一个独立的程序,一个完整的可运行的软件系统有若干个单元组成,所以必须为每个单元测试开发驱动单元和桩单元。

驱动单元(Driver):所测函数的主程序,它接收测试数据,并把数据传递给所测试单元,最后再输出实际测试结果,当被测单元能完成相关单元时,也可以不需要驱动单元。
桩单元(Stub):用来代替所测单元调用的子单元。

单元测试的测试策略

孤立的测试策略
自顶向下测试测试策略
自底向上的测试策略

knowledge is no pay,reward is kindness
0%